package com.iha.pongzor.ContentProvider;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

import com.iha.pongzor.database.HighscoreDbHelper;
import com.iha.pongzor.database.HighscoreTable;
import com.iha.pongzor.logic.AppHelper;
import com.iha.pongzor.data.HighScore;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;

public class HighScoreDB_CP extends ContentProvider {

	// database helper
	private HighscoreDbHelper database;

	// Used for the UriMacher
	private static final int OFFLINE_HIGHSCORES = 10;
	private static final int OFFLINE_HIGHSCORE_ID = 20;

	private static final int ONLINE_HIGHSCORES = 11;
	private static final int ONLINE_HIGHSCORE_ID = 21;

	private static final String AUTHORITY = "com.iha.pongzor.ContentProvider.highscoredb_cp";

	private static final String BASE_PATH = "pongzor";
	public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);

	public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/highScores";
	public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + "/highScore";

	private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
	static {
		sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/online", ONLINE_HIGHSCORES);
		sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/offline", OFFLINE_HIGHSCORES);
		sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/online/#", ONLINE_HIGHSCORE_ID);
		sURIMatcher.addURI(AUTHORITY, BASE_PATH + "/offline/#", OFFLINE_HIGHSCORE_ID);
	}

	/**
	 * @see android.content.ContentProvider#onCreate()
	 */
	@Override
	public boolean onCreate() {
		database = new HighscoreDbHelper(getContext());
		// TODO figureout why false is used
		// Example from:
		// http://www.vogella.com/articles/AndroidSQLite/article.html#databasetutorial
		return false;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

		Cursor cursor;

		int uriType = sURIMatcher.match(uri);
		switch (uriType) {
		case OFFLINE_HIGHSCORES:
			cursor = createOfflineCurser(-1, projection, selection, selectionArgs, sortOrder);
			break;
		case OFFLINE_HIGHSCORE_ID:
			cursor = createOfflineCurser(Integer.parseInt(uri.getLastPathSegment()), projection, selection, selectionArgs, sortOrder);
			// Adding the ID to the original query
			break;
		case ONLINE_HIGHSCORES:
			cursor = createOnlineCurser(-1);
			break;
		case ONLINE_HIGHSCORE_ID:
			cursor = createOnlineCurser(Integer.parseInt(uri.getLastPathSegment()));
			break;
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}

		// Make sure that potential listeners are getting notified
		cursor.setNotificationUri(getContext().getContentResolver(), uri);

		return cursor;
	}

	private Cursor createOfflineCurser(int id, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
		Cursor c;

		// Uisng SQLiteQueryBuilder instead of query() method
		SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

		// Check if the caller has requested a column which does not exists
		checkColumns(projection);

		// Set the table
		queryBuilder.setTables(HighscoreTable.TABLE_NAME);

		if (id != -1) {
			queryBuilder.appendWhere(HighscoreTable.COLUMN_ID + "=" + id);
		}

		SQLiteDatabase db = database.getWritableDatabase();
		c = queryBuilder.query(db, projection, selection, selectionArgs, null, null, HighscoreTable.COLUMN_SCORE + " DESC");

		return c;
	}

	private Cursor createOnlineCurser(int id) {
		
		String[] columns = { HighscoreTable.COLUMN_ID, HighscoreTable.COLUMN_NAME, HighscoreTable.COLUMN_SCORE, HighscoreTable.COLUMN_SECONDS, HighscoreTable.COLUMN_date };

		List<HighScore> hsList = AppHelper.fetchHighscore();
		MatrixCursor c = new MatrixCursor(columns, hsList.size());

		Collections.sort(hsList);

		if (id != -1) {
			int i = id;
			Object[] columnValues = { i, hsList.get(i).getName(), hsList.get(i).getScore(), hsList.get(i).getSeconds(), hsList.get(i).getDate() };
			c.addRow(columnValues);
		} else {
			for (int i = 0; i < hsList.size(); i++) {
				Object[] columnValues = { i, hsList.get(i).getName(), hsList.get(i).getScore(), hsList.get(i).getSeconds(), hsList.get(i).getDate() };
				c.addRow(columnValues);
			}
		}

		return c;
	}

	@Override
	public String getType(Uri uri) {
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		int uriType = sURIMatcher.match(uri);
		SQLiteDatabase sqlDB = database.getWritableDatabase();
		
		SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext()); 
		String name = pref.getString("name", "Unknown");
		String date = new Date().toLocaleString();

		long id = 0;
		switch (uriType) {
		case OFFLINE_HIGHSCORES:
			values.put(HighscoreTable.COLUMN_NAME, name);
			values.put(HighscoreTable.COLUMN_date, date);
			id = sqlDB.insert(HighscoreTable.TABLE_NAME, null, values);
			break;
		case ONLINE_HIGHSCORES:
			
//			String name = values.getAsString(HighscoreTable.COLUMN_NAME);
			int score = values.getAsInteger(HighscoreTable.COLUMN_SCORE);
			int duration = values.getAsInteger(HighscoreTable.COLUMN_SECONDS);
//			String date = values.getAsString(HighscoreTable.COLUMN_date);

			HighScore h = new HighScore(name, score, duration, date);
			AppHelper.sendHighscore(h);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);
		return Uri.parse(BASE_PATH + "/" + id);
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		int uriType = sURIMatcher.match(uri);
		SQLiteDatabase sqlDB = database.getWritableDatabase();
		int rowsDeleted = 0;
		switch (uriType) {
		case OFFLINE_HIGHSCORES:
			rowsDeleted = sqlDB.delete(HighscoreTable.TABLE_NAME, selection, selectionArgs);
			break;
		case OFFLINE_HIGHSCORE_ID:
			String id = uri.getLastPathSegment();
			if (TextUtils.isEmpty(selection))
				rowsDeleted = sqlDB.delete(HighscoreTable.TABLE_NAME, HighscoreTable.COLUMN_ID + "=" + id, null);
			else
				rowsDeleted = sqlDB.delete(HighscoreTable.TABLE_NAME, HighscoreTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);
		return rowsDeleted;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

		int uriType = sURIMatcher.match(uri);
		SQLiteDatabase sqlDB = database.getWritableDatabase();
		int rowsUpdated = 0;
		switch (uriType) {
		case OFFLINE_HIGHSCORES:
			rowsUpdated = sqlDB.update(HighscoreTable.TABLE_NAME, values, selection, selectionArgs);
			break;
		case OFFLINE_HIGHSCORE_ID:
			String id = uri.getLastPathSegment();
			if (TextUtils.isEmpty(selection))
				rowsUpdated = sqlDB.update(HighscoreTable.TABLE_NAME, values, HighscoreTable.COLUMN_ID + "=" + id, selectionArgs);
			else
				rowsUpdated = sqlDB.update(HighscoreTable.TABLE_NAME, values, HighscoreTable.COLUMN_ID + "=" + id + " and " + selection, selectionArgs);
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);
		return rowsUpdated;
	}

	private void checkColumns(String[] projection) {
		String[] availale = { HighscoreTable.COLUMN_NAME, HighscoreTable.COLUMN_date, HighscoreTable.COLUMN_SCORE, HighscoreTable.COLUMN_SECONDS, HighscoreTable.COLUMN_ID, };
		if (projection != null) {
			HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
			HashSet<String> availaleColumns = new HashSet<String>(Arrays.asList(availale));
			// Check if all columns which are requested are available
			if (!availaleColumns.containsAll(requestedColumns)) {
				throw new IllegalArgumentException("Unknown columns in projection");
			}
		}
	}

}
